#! /usr/bin/env python
__author__="Hong Phuc Bui, Sarah Theobald "
__date__ ="$Nov 27, 2011 10:54:44 AM$"



import prime
import random
import xtea
from pythoncrypt.groestl.hash import groestlHash

def powerMod(b,e,m):#
	r'''
		berechnet :math:`b^e \mod m`
		
		:param b: integer Wert
		:param e: integer Wert
		:param m: integer Wert
		
	'''
	r = 1
	while e != 0:
		if (e & 1) == 1:
			r = (r*b) % m
		e = e >> 1
		b = (b*b) % m
	
	return r

def searchFirstErzeuger(p, factor):#
	'''
	
Sucht den ersten Erzeuger in der Group :math:`\mathbf{F}_p`

:param p:	  eine Primzahl
:param factor: 2-Dimensionale Array von Prime-Faktoren von ``p-1``, in Format ``[[p_1,e_1] , [p_2, e_2] ... ]``.
	Dabei sind ``p_1``, ``p_2``, ... die Primen, ``e_1``, ``e_2``, ... die entsprechenden Exponenten.

	'''
	
	isErzeuger = True
	g = 0
	while g <= p-1:
		g +=1; 
	#for g in range(1,p):
		# print "g = %d" %g
		isErzeuger = True
		for i in range(0,len(factor)):
			# print "\t p_i = %d" %factor[i][0]
			e = (p-1)/factor[i][0]
			# print "\t e = %d" %e
			r = powerMod(g, e, p)
			# print "\t r = %d" %r
			if r == 1:
				isErzeuger = False
				break;
			
		if isErzeuger:
			return g
		
class DHCrypt():#
	'''
		Diese Klasse fuhert alle Schritte in die Diffie-Hellman Key Exchange
		aus. Sie verwendet die Primzahl in der Module :py:mod:`~pythoncrypt.diffieHellmanXTEA.prime`.
		Dieses Module ist von PARI/GP generiert wird. Die Client muss dieses Module
		kopieren.
	'''

	def __init__(self):
		self.p = prime.prime
		self.r = random.randint(2,self.p-1)
		self.a = searchFirstErzeuger(self.p, prime.primeFactor)
		self.xtea_obj = xtea.XTEA()
		self.key = None
		 
	def setup(self,r,g,a):#
		'''
			Diese Methode ist fuer die Einstellung und
			Validierung von ``r``, ``g``, ``a`` in der Laufzeit gedacht,
			wird aber nicht implementiert.
		'''
		self.r = r
		self.p = g
		self.a = a
		# TODO: check if (r,g,a) valid
	
	
	def handSchack(self):#
		'''
			generates :math:`a^r` and saves in ``self.base``. This value (``self.base``)
			is to be send to partner.

			:rtype: ``int`` (``long int``)
		'''
		self.base = powerMod(self.a, self.r, self.p)
		return self.base
	
	
	def xteaEncode(self,plaintext):#
		'''
			verschluesslt ``plaintext`` als String in Hexadezimal
			
			:param plaintext: die Nachricht in Klartext (64 Byte)
			:return: verschluesselte Nachricht als String in Hexadezimal

		'''
		encrypt = self.xtea_obj.strencode(self.key, plaintext)
		return encrypt
	
	def xteaDecode(self, encryptedText):#
		'''
			
			Entschluesslt ``encryptedText`` in Klartext
			
			:param plaintext: die Nachricht in Klartext (64 Byte)
			:return: entschluesselte Nachricht als String in Hexadezimal

		'''
		decrypt = self.xtea_obj.strdecode(self.key, encryptedText)
		return decrypt
	
	def genCommonKey(self,partner_base):#
		'''
			generates common key from the ``partner_base``, which comes from communication's partner.
			The length of the generated key is  compatible 128 Bit. The key is generated in three steps:

				* perform :math:`(a^s)^r`
				* convert the result to a string
				* use the Groestl Hash to get the string of length 128 Bits. Because the implementation
					of the Groeslt Hash function returns a string of hexadecimal digits, the hash function
					must be call to return 64 bits to generate a string with the length of 128 bits. (One
					digit (``0`` to ``F`` also  4 bits) is converted in one character (also one byte).
			
			:param partner_base: :math:`(a^s)` 
			:return: the common key. This key is also saved in ``self.key``.
			:rtype: ``str``
		'''
		int_key = powerMod(partner_base, self.r, self.p)
		self.key = groestlHash(str(int_key), 64)
		return self.key
	



